package com.lbb.springbootstock.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;

import com.lbb.springbootstock.bean.RequestBody;
import com.lbb.springbootstock.bean.RequestItem;
import com.lbb.springbootstock.bean.StockDay;
import com.lbb.springbootstock.client.JdbcUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * 获取股票的历史数据以及计算20日k线 40日k线 60日k线
 **/
public class StockHistoryService {

    private static final String URL = "http://api.tushare.pro";
    private static final String TOKEN = "0488aa6054d08b2d36465ab6c5ed08a02b7b36346ecf889364536ec6";
    private static final String DAYNAME = "daily";
    private static final String WEENAME = "weekly";
    private static final String MonthNAME = "monthly";
    private static ExecutorService executor = Executors.newFixedThreadPool(3);
    private static CountDownLatch latch = new CountDownLatch(3);
    private static String start_A = null;
    private static String end_A = null;
    //选股条件
    private static Long sz = 50000000000L;

    public static void main(String[] args) throws Exception {
        pre();
    }

    public static void pre() throws Exception {
        getLastData();
        System.out.println("获取数据结束444");
        doJob();
        cal();
    }


    public static void getLastData() throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        Statement statement = connection.createStatement();
        SimpleDateFormat sf = new SimpleDateFormat("YYYYMMdd");
        String date = sf.format(new Date());
        String preSql = "create table stock" + date + " as select * from stock";
        statement.execute(preSql);
        String sql = "truncate table stock;";
        statement.execute(sql);
        StockListService.getStockList();
    }

    public static void doJob() throws SQLException, InterruptedException {
        System.out.println("eeee");
        ArrayList<String> codes = getAllStockCde();
        System.out.println("code数量:" + codes.size());
        for (String code : codes) {
            getDayDataByCode(code);
        }
    }


    public static void getDayDataByCode(String code) throws SQLException, InterruptedException {
        String data = getStartEnd();
        String startTime = data.split(",")[0];
        String endTime = data.split(",")[1];
        System.out.println(startTime + "----------------");
        System.out.println(endTime + "----------------");
        RequestItem item = new RequestItem();
        item.setStart_date(startTime);
        item.setEnd_date(endTime);
        item.setTs_code(code);
        RequestBody requestBody = new RequestBody();
        requestBody.setApi_name(DAYNAME);
        requestBody.setToken(TOKEN);
        requestBody.setParams(item);
        String bodyData = JSON.toJSONString(requestBody);
        System.out.println("bodyData:");
        System.out.println(bodyData);
        String result = sendRequest(bodyData);
        String before = result;
        int start = result.indexOf("[[");
        int end = result.indexOf("]]") + 2;
        result = result.substring(start, end);
        System.out.println(result);
        JSONArray parse = (JSONArray) JSON.parse(result);
        List<StockDay> stocks = new ArrayList<>();
        for (int i = 0; i < parse.size(); i++) {
            JSONArray o = (JSONArray) parse.get(i);
            StockDay stockDay = new StockDay();
            for (int j = 0; j < 11; j++) {
                stockDay.setTsCode(o.getString(0));
                stockDay.setTradeDate(o.getString(1));
                stockDay.setOpen(o.getBigDecimal(2).doubleValue() + "");
                stockDay.setHigh(o.getBigDecimal(3).doubleValue() + "");
                stockDay.setLow(o.getBigDecimal(4).doubleValue() + "");
                stockDay.setClose(o.getBigDecimal(5).doubleValue() + "");
                stockDay.setPreClose(o.getBigDecimal(6).doubleValue() + "");
                stockDay.setChange(o.getBigDecimal(7).doubleValue() + "");
                stockDay.setPctChg(o.getBigDecimal(8).doubleValue() + "");
                stockDay.setVol(o.getBigDecimal(9).doubleValue() + "");
                stockDay.setAmount(o.getBigDecimal(10).doubleValue() + "");
            }
            stocks.add(stockDay);
        }
        System.out.println(parse);
        save(stocks);
    }

    private static void cal() throws SQLException {
        //计算20日k线、40日k线、60日k线
        ArrayList<String> codes = getAllStockCde();
        for (String code : codes) {
            double v60 = 0.0;
            double v40 = 0.0;
            double v20 = 0.0;
            double sum60 = 0.0;
            double sum40 = 0.0;
            double sum20 = 0.0;
            double cz = 0.0;
            ArrayList<StockDay> data = get60DayData(code);
            int size = data.size();
            int mm = 0;
            if (size >= 60) {
                mm = 60;
            } else {
                mm = size;
            }
            for (int i = 0; i < mm; i++) {
                StockDay stockDay = data.get(i);
                if (i < 20) {
                    sum20 += Double.parseDouble(stockDay.getClose());
                    sum40 += Double.parseDouble(stockDay.getClose());
                    sum60 += Double.parseDouble(stockDay.getClose());
                } else if (i < 40) {
                    sum40 += Double.parseDouble(stockDay.getClose());
                    sum60 += Double.parseDouble(stockDay.getClose());
                } else {
                    sum60 += Double.parseDouble(stockDay.getClose());
                }
            }
            v20 = sum20 / 20;
            v40 = sum40 / 40;
            v60 = sum60 / 60;
            cz = Double.parseDouble(data.get(0).getClose()) - v60;
            saveCz(code, v20, v40, v60, cz);
        }

    }

    private static void saveCz(String code, double v20, double v40, double v60, double cz) throws SQLException {
        System.out.println(code + "----" + v20 + "-----" + v60 + "-----" + cz);

        Connection connection = JdbcUtil.getConnection();
        PreparedStatement ps = connection.prepareStatement("UPDATE stock SET v20 = ? " + ",v40 = ?,v60 = ? ,cz = ? WHERE Market_Symbol = ? ");
        ps.setString(1, v20 + "");
        ps.setString(2, v40 + "");
        ps.setString(3, v60 + "");
        ps.setString(4, cz + "");
        ps.setString(5, code.substring(0, 6));
        ps.execute();
    }

    private static ArrayList<StockDay> get60DayData(String code) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        String sql = "select * from stock_day where ts_code = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        ps.setString(1, code);
        ResultSet resultSet = ps.executeQuery();
        ArrayList<StockDay> list = new ArrayList<>();
        while (resultSet.next()) {
            StockDay stock = new StockDay();
            stock.setTsCode(resultSet.getString(2));
            stock.setClose(resultSet.getString(7));
            list.add(stock);
        }
        return list;
    }

    /**
     * 日数据全量数据
     */
    public static void getDataByStockCode() throws SQLException, InterruptedException {
        Integer offset = 1;
        Integer limit = 5000;
        String data = getStartEnd();
        String startTime = data.split(",")[0];
        String endTime = data.split(",")[1];
        RequestItem item = new RequestItem();
        item.setOffset(offset);
        item.setLimit(limit);
        RequestBody requestBody = new RequestBody();
        requestBody.setApi_name(DAYNAME);
        requestBody.setToken(TOKEN);
        requestBody.setParams(item);
        String bodyData = JSON.toJSONString(requestBody);
        String result = sendRequest(bodyData);
        String before = result;

        int start = result.indexOf("[[");
        int end = result.indexOf("]]") + 2;
        result = result.substring(start, end);
        System.out.println(result);
        JSONArray parse = (JSONArray) JSON.parse(result);
        List<StockDay> stocks = new ArrayList<>();
        for (int i = 0; i < parse.size(); i++) {
            JSONArray o = (JSONArray) parse.get(i);
            StockDay stockDay = new StockDay();
            for (int j = 0; j < 11; j++) {
                stockDay.setTsCode(o.getString(0));
                stockDay.setTradeDate(o.getString(1));
                stockDay.setOpen(o.getBigDecimal(2).doubleValue() + "");
                stockDay.setHigh(o.getBigDecimal(3).doubleValue() + "");
                stockDay.setLow(o.getBigDecimal(4).doubleValue() + "");
                stockDay.setClose(o.getBigDecimal(5).doubleValue() + "");
                stockDay.setPreClose(o.getBigDecimal(6).doubleValue() + "");
                stockDay.setChange(o.getBigDecimal(7).doubleValue() + "");
                stockDay.setPctChg(o.getBigDecimal(8).doubleValue() + "");
                stockDay.setVol(o.getBigDecimal(9).doubleValue() + "");
                stockDay.setAmount(o.getBigDecimal(10).doubleValue() + "");
            }
            stocks.add(stockDay);
        }
        System.out.println(parse);
        save(stocks);
        while (before.indexOf("true") != -1) {
            Thread.sleep(1000);
            offset = limit + 1;
            limit = limit + 5000;
            item = new RequestItem();
            item.setOffset(offset);
            item.setLimit(limit);
            requestBody = new RequestBody();
            requestBody.setApi_name(DAYNAME);
            requestBody.setToken(TOKEN);
            requestBody.setParams(item);
            bodyData = JSON.toJSONString(requestBody);
            result = sendRequest(bodyData);
            before = result;
            start = result.indexOf("[[");
            end = result.indexOf("]]") + 2;
            result = result.substring(start, end);
            System.out.println(result);
            parse = (JSONArray) JSON.parse(result);
            stocks = new ArrayList<>();
            for (int i = 0; i < parse.size(); i++) {
                JSONArray o = (JSONArray) parse.get(i);
                StockDay stockDay = new StockDay();
                for (int j = 0; j < 11; j++) {
                    stockDay.setTsCode(o.getString(0));
                    stockDay.setTradeDate(o.getString(1));
                    stockDay.setOpen(o.getBigDecimal(2).doubleValue() + "");
                    stockDay.setHigh(o.getBigDecimal(3).doubleValue() + "");
                    stockDay.setLow(o.getBigDecimal(4).doubleValue() + "");
                    stockDay.setClose(o.getBigDecimal(5).doubleValue() + "");
                    stockDay.setPreClose(o.getBigDecimal(6).doubleValue() + "");
                    stockDay.setChange(o.getBigDecimal(7).doubleValue() + "");
                    stockDay.setPctChg(o.getBigDecimal(8).doubleValue() + "");
                    stockDay.setVol(o.getBigDecimal(9).doubleValue() + "");
                    stockDay.setAmount(o.getBigDecimal(10).doubleValue() + "");
                }
                stocks.add(stockDay);
            }
            System.out.println(parse);
            save(stocks);
        }

    }


    public static void save(List<StockDay> stocks) throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        PreparedStatement ps = connection.prepareStatement(
                "INSERT into stock_day (`ts_code`,`trade_date`,`open`,`high`,`low`,`close`,`pre_close`,`change`,`pct_chg`,`vol`,`amount`) values (?,?,?,?,?,?,?,?,?,?,?)");
        for (StockDay item : stocks) {
            ps.setString(1, item.getTsCode());
            ps.setString(2, item.getTradeDate());
            ps.setString(3, item.getOpen());
            ps.setString(4, item.getHigh());
            ps.setString(5, item.getLow());
            ps.setString(6, item.getClose());
            ps.setString(7, item.getPreClose());
            ps.setString(8, item.getChange());
            ps.setString(9, item.getPctChg());
            ps.setString(10, item.getVol());
            ps.setString(11, item.getAmount());
            ps.addBatch();
        }
        ps.executeBatch();
    }


    private static String sendRequest(String bodyData) {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(URL);
        httpPost.setEntity(new StringEntity(bodyData, "UTF-8"));
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                return EntityUtils.toString(responseEntity);
            }
        } catch (Exception e) {
            System.out.println("连接失败" + e.getMessage());
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    //获取所有股票编码
    private static ArrayList<String> getAllStockCde() throws SQLException {
        Connection connection = JdbcUtil.getConnection();
        Statement statement = connection.createStatement();
        String sql = "select code from stock_base;";
        ResultSet resultSet = statement.executeQuery(sql);
        ArrayList<String> list = new ArrayList<>();
        while (resultSet.next()) {
            list.add(resultSet.getString(1));
        }
        return list;
    }

    /**
     * 获取数据起始时间
     */
    private static String getStartEnd() throws SQLException {
        if (start_A != null && end_A != null) {
            return start_A + "," + end_A;
        }
        Connection connection = JdbcUtil.getConnection();
        Statement statement = connection.createStatement();
        String sql = "select count(*) from stock_day";
        ResultSet resultSet = statement.executeQuery(sql);
        int num = 0;
        while (resultSet.next()) {
            num = resultSet.getInt(1);
        }
        if (num == 0) {
            GregorianCalendar calendar = new GregorianCalendar();
            calendar.add(GregorianCalendar.DATE, -100);
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
            String start = format.format(calendar.getTime());
            String end = format.format(new Date());
            start_A = start;
            end_A = end;
            return start + "," + end;
        } else {
            String start = "";
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
            String end = format.format(new Date());
            sql = "select MAX(trade_date) from stock_day;";
            resultSet = statement.executeQuery(sql);
            while (resultSet.next()) {
                start = resultSet.getString(1);
            }
            if (!start.equals(end)) {
                start = Integer.parseInt(start) + 1 + "";
            }
            start_A = start;
            end_A = end;
            return start + "," + end;
        }
    }
}
